package top.xlq.mydb.backend.tm;

import top.xlq.mydb.backend.utils.Panic;
import top.xlq.mydb.common.Error;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.RandomAccessFile;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;

public interface TransactionManager {
    Long begin();// 开启一个新事务

    void commit(long xid);// 提交一个事务

    void abort(long xid); // 取消一个事务

    boolean isActive(long xid);// 查询一个事务的状态是否是正在进行的状态

    boolean isCommitted(long xid);// 查询一个事务的状态是否是已提交

    boolean isAborted(long xid);// 查询一个事务的状态是否是已取消

    void close();// 关闭 TM

    /**
     * 创建一个xid文件
     *
     * @return
     */
    public static TransactionManagerImpl create(String path) {
        File f = new File(path + TransactionManagerImpl.XID_SUFFIX);
        // 判断文件是否新创建
        try {
            if (!f.createNewFile()) {
                Panic.panic(Error.FileExistsException);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
        //判断是否可读
        if (!f.canRead() || !f.canWrite()) {
            Panic.panic(Error.FileCannotRWException);
        }
        // 写入一个xidCounter头部
        byte[] arr = new byte[TransactionManagerImpl.LEN_XID_HEADER_LENGTH];
        ByteBuffer buffer = ByteBuffer.wrap(arr);
        RandomAccessFile randomAccessFile = null;
        FileChannel fc = null;
        try {
            randomAccessFile = new RandomAccessFile(f, "rw");
            fc = randomAccessFile.getChannel();
            fc.position(0);
            fc.write(buffer);
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return new TransactionManagerImpl(randomAccessFile, fc);
    }

    /**
     * 打开已存在的xid文件
     *
     * @param path
     * @return
     */
    public static TransactionManagerImpl open(String path) {
        File f = new File(path + TransactionManagerImpl.XID_SUFFIX);

        if (!f.exists()) {
            Panic.panic(Error.FileNotExistsException);
        }
        //判断是否可读
        if (f.canRead() && f.canWrite()) {
            Panic.panic(Error.FileCannotRWException);
        }
        RandomAccessFile randomAccessFile = null;
        FileChannel fc = null;
        try {
            randomAccessFile = new RandomAccessFile(f, "rw");
            fc = randomAccessFile.getChannel();
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        }
        return new TransactionManagerImpl(randomAccessFile,fc);
    }
}
